﻿// ## 2023/11/20 # 铃 # 优化主要函数,战略AI.兵种特性.新特技等().新增大量逻辑 ##
// ## 2023/11/18 # 铃 # 优化主要函数,兵粮计算,兵装计算.水上兵器计算
// ## 2023/11/13 # 铃 # 优化主要函数,出征判决,出征数量,野战判断.
// ## 2023/11/3 #  铃  # 把武将调度相关的全都换成当前版本既有逻辑725-727.删除运输队相关的逻辑(性能很差,且逻辑有严重问题)
// ## 2023/5/6 #  铃  # 基于马术书的设计理念,重构功能

namespace AI优化_据点防御支援
{
    const int 据点防御支援_战斗部队数 = 8;
    const int 据点进攻支援_战斗部队数 = 12;
    const int 据点进攻支援_攻城部队数 = 5;

    //------------------------------------------------------------
    pk::c_bool 调试模式 = pk::c_bool(false);
    pk::c_bool 调试模式2 = pk::c_bool(false);
    pk::c_bool 调试模式3 = pk::c_bool(false);
    pk::c_bool 调试模式4 = pk::c_bool(false);
    //=======================================================================================

    class Main
    {
        pk::force @force_t;
        int siege_count = 0;
        int unit_count = 0;


        //------------------------------------------------------------
        pk::c_bool 调试模式 = pk::c_bool(false);
        pk::c_bool 调试模式2 = pk::c_bool(false);
        pk::c_bool 调试模式3 = pk::c_bool(false);
        pk::c_bool 调试模式4 = pk::c_bool(false);

        Main()
        {
            pk::bind(111, pk::trigger111_t(onTurnStart));

            pk::bind(260, pk::trigger260_t(据点援军_701_打印));
        }

        void 据点援军_701_打印()
        {
            ImGui::Checkbox("调试模式", 调试模式);
            ImGui::Checkbox("进攻支援", 调试模式2);
            ImGui::Checkbox("防守支援", 调试模式3);
            ImGui::Checkbox("查询可用据点细节", 调试模式4);
        }

        void onTurnStart(pk::force @force)
        {
            int force_id = force.get_id();
            @force_t = @force;

            if (force.get_id() != pk::get_current_turn_force_id()) return;

            if (pk::is_normal_force(force_id) and pk::get_elapsed_months() > 6 and ch::get_base_list(force).count > 1)
            {
                据点防御支援(force);
                据点进攻支援(force);
            }
            return;
        }

        //---------------------------------------------------------------------------------------
        //          据点防御支援执行函数
        //---------------------------------------------------------------------------------------

        pk::list<pk::building @> list_reinforce_base;   // 出征据点列表

        int 出征部队;

        //----- 据点防御支援执行函数
        void 据点防御支援(pk::force @force)
        {
            int force_id = force.get_id();

            list_reinforce_base.clear();

            pk::list<pk::building @> building_list = ch::get_base_list(force);

            for (int i = 0; i < building_list.count; i++)
            {
                pk::building @base = building_list[i];
                int base_id = base.get_id();


                int 周围己方兵力 = ai::base_around_self_troops[base_id];
                int 周围敌方兵力 = ai::base_around_enemy_troops[base_id];
                int 据点范围敌方兵力 = ai::base_in_range_enemy_troops[base_id];
                int 据点内可用战斗兵力 = ai::base_max_effective_troops[base_id];
                int 正在攻击己方的兵力 = 0;

                for (int j = 0; j < 据点_末; j++)
                {
                        正在攻击己方的兵力 += ai::base_attack_base_troops[j][i];

                }

                if (调试模式3.v) pk::trace(pk::format("1{}前置判断,周围敌方兵力{},周围己方兵力{},正在攻击己方的兵力{},据点范围敌方兵力{},据点内可用战斗兵力{})", pk::decode(pk::get_name(base)), 周围敌方兵力, 周围己方兵力, 正在攻击己方的兵力, 据点范围敌方兵力, 据点内可用战斗兵力));

                // 5格内有敌人才行
                if (据点内可用战斗兵力 + 周围己方兵力 < int(pk::max(正在攻击己方的兵力, 周围敌方兵力) * 1.2) and 据点内可用战斗兵力 + 周围己方兵力 < int(据点范围敌方兵力 * 1.2) and 周围敌方兵力 > 5000)
                {
                    if (调试模式3.v) pk::trace(pk::format("2{}需要支援,周围敌方兵力{},周围己方兵力{},正在攻击己方的兵力{},据点范围敌方兵力{},据点内可用战斗兵力{})", pk::decode(pk::get_name(base)), 周围敌方兵力, 周围己方兵力, 正在攻击己方的兵力, 据点范围敌方兵力, 据点内可用战斗兵力));
                    // 寻找可以出征的候选据点
                    int src_target = find_near_self_base(base, force, /*type 0为进攻,1为防御*/ 1);
                    if (src_target != -1)
                    {
                        if (调试模式3.v) pk::trace(pk::format("3{}需要支援.{}被选中", pk::decode(pk::get_name(base)), pk::decode(pk::get_name(pk::get_building(src_target)))));

                        // 向需要援军的据点派遣援军
                        出征部队 = 0;       // 初始化已出征战斗部队数
                        int push_count = 0; // 检查推送次数的变量
                        int 需要支援部队 = int((据点范围敌方兵力 * 1.5 - 据点内可用战斗兵力 - 周围己方兵力) / 5000 + 周围敌方兵力 / 5000 + 1);

                        // 对付玩家的时候支援要更加积极
                        if (ai::base_in_range_enemy_troops_from_player[base_id] > 20000)
                            需要支援部队 = 需要支援部队 + 2;

                        int 最大可出征部队 = pk::max(1, pk::min(据点防御支援_战斗部队数, 需要支援部队));

                        // 包括出征据点搜索，执行出征命令的重复次数
                        bool cmd = false;
                        while (出征部队 < 最大可出征部队 and push_count < 最大可出征部队)
                        {
                            push_count += 1;
                            cmd = (push_defense_unit(base, pk::get_building(src_target)) or cmd); // 援军出征
                        }
                    }
                }
            }
            list_reinforce_base.clear();
        }

        //*******************************************  防御支援单位出征前置判决 ****************************************************************
        bool push_defense_unit(pk::building @dst_base, pk::building @src_base)
        {
            int src_id = src_base.get_id();
            int dst_id = dst_base.get_id();

            // 出征基地与目标基地之间的距离
            int distance = pk::get_building_distance(src_id, dst_id, src_base.get_force_id());

            int 最大可出征部队 = 据点防御支援_战斗部队数;

            int push_count = 0; // 检查 push 次数的变量

            // 在出征据点反复执行出征命令
            while (出征部队 < 最大可出征部队 and push_count < 最大可出征部队)
            {
                push_count += 1;

                int unit_id = push_battle_unit(src_base, dst_base, true, /*type 0为进攻,1为防御*/ 1);
                if (unit_id != -1)
                {
                    出征部队 += 1; // 战斗部队计数
                    if (!list_reinforce_base.contains(src_base))
                        list_reinforce_base.add(src_base);
                }
            }
            if ((出征部队) > 0)
                return true;

            return false;
        }

        //---------------------------------------------------------------------------------------
        //          据点进攻支援执行函数
        //---------------------------------------------------------------------------------------

        pk::list<pk::building @> list_target_base; // 需要攻击的交战据点列表
        pk::list<pk::building @> list_attack_base; // 攻击部队出征据点列表

        void 据点进攻支援(pk::force @force)
        {
            int force_id = force.get_id();

            // 每回合更新势力城市区域：交战中的部队数量和编队数量

            list_target_base.clear();
            list_attack_base.clear();

            // 获取己方正在攻击或者征服的目标据点
            pk::list<pk::unit @> unit_list = pk::get_unit_list(force);
            int total_unit_troops = 0;

            for (int i = 0; i < 据点_末; i++)
            {
                pk::building @dst_base = pk::get_building(i);
                if (调试模式2.v)pk::trace(pk::format("对{}的据点进攻人数{}.({}军))", pk::decode(pk::get_name(dst_base)), ai::force_attack_base_troops[force.get_id()][i], pk::decode(pk::get_name(force))));
                if (ai::force_attack_base_troops[force.get_id()][i] > 6000 or (dst_base.get_force_id() == -1 and pk::get_elapsed_months() > 9))  //对空城派遣援军
                {
                    if (调试模式2.v)pk::trace(pk::format("对{}的据点选择.({}军))", pk::decode(pk::get_name(dst_base)), pk::decode(pk::get_name(force))));
                    int src_target = find_near_self_base(dst_base, force, /*type 0为进攻,1为防御*/ 0);
                    pk::building @src_base = pk::get_building(src_target);
                    if (pk::is_alive(src_base) and !list_target_base.contains(dst_base))
                    {
                        list_target_base.add(dst_base);
                        if (调试模式2.v) pk::trace(pk::format("对{}的据点选择.{}被加入列表)", pk::decode(pk::get_name(dst_base)), pk::decode(pk::get_name(src_base))));
                    }
                }
            }

            // 按兵力排序
            list_target_base.sort(function(a, b) {
                return pk::get_troops(a) < pk::get_troops(b);
            });

            // 依次向需要攻击的据点派遣支援部队
            pk::array<pk::building @> arr_target_base = pk::list_to_array(list_target_base);
            for (int i = 0; i < int(arr_target_base.length); i++)
            {

                list_attack_base.clear();
                pk::building @dst_base = arr_target_base[i];
                if (调试模式2.v) pk::trace(pk::format("第一次派遣,对{}的据点发送攻击指令.({}军))", pk::decode(pk::get_name(dst_base)), pk::decode(pk::get_name(force))));
                bool cmd = push_attack(dst_base, force);

                if (调试模式2.v) pk::trace(pk::format("第二次派遣,对{}的据点发送攻击指令.({}军))", pk::decode(pk::get_name(dst_base)), pk::decode(pk::get_name(force))));
                cmd = push_attack(dst_base, force);

                if (调试模式2.v) pk::trace(pk::format("第三次派遣,对{}的据点发送攻击指令.({}军))", pk::decode(pk::get_name(dst_base)), pk::decode(pk::get_name(force))));
                cmd = push_attack(dst_base, force);
            }

            list_target_base.clear();
            list_attack_base.clear();
        }
        //---------------------------------------------------------------------------------------
        // 指定发送到攻击目标的部队类型
        bool push_attack(pk::building @dst_base, pk::force @force)
        {
            // 检查是否有附近的基地可以派遣援军
            int src_target = find_near_self_base(dst_base, force, /*type 0为进攻,1为防御*/ 0);
            if (src_target == -1 or pk::is_player_controlled(pk::get_building(src_target)))
                return false;

            if (调试模式2.v)  pk::trace(pk::format("一.对{}的据点选择.找到可用据点{},({}军))", pk::decode(pk::get_name(dst_base)), pk::decode(pk::get_name(pk::get_building(src_target))), pk::decode(pk::get_name(force))));

            // 攻击部队出发地点
            pk::building @src_base = pk::get_building(src_target);

            auto person_list = pk::get_idle_person_list(src_base);
            if (person_list.count == 0)
                return false; // 武将不足

            if (调试模式2.v)  pk::trace(pk::format("二.对{}的据点选择.找到可用据点{},({}军))", pk::decode(pk::get_name(dst_base)), pk::decode(pk::get_name(pk::get_building(src_target))), pk::decode(pk::get_name(force))));


            // 根据敌方兵力数,计算留存量,可用兵力小于留存量则不支援.
            int ref_troops = ai::retained_troops[src_base.get_id()];

            /// 和玩家相邻不止一个,而且进攻的不为玩家据点,则非常保守
            if (ch::get_neighbor_player_base(src_base) >= 1 and !dst_base.is_player())
                ref_troops += ch::get_neighbor_player_base(src_base) * 10000 + 10000;

            if (int(pk::get_troops(src_base)) < ref_troops)
                return false; // 兵力不足

            if (调试模式2.v)  pk::trace(pk::format("三.对{}的据点选择.找到可用据点{},({}军))", pk::decode(pk::get_name(dst_base)), pk::decode(pk::get_name(pk::get_building(src_target))), pk::decode(pk::get_name(force))));

            int src_troops = pk::get_troops(src_base);
            int src_food = pk::get_food(src_base);

            if (src_food < int(2.0f * ref_troops))
                return false;

            if (调试模式2.v)  pk::trace(pk::format("四.对{}的据点选择.找到可用据点{},({}军))", pk::decode(pk::get_name(dst_base)), pk::decode(pk::get_name(pk::get_building(src_target))), pk::decode(pk::get_name(force))));

            int building_id = pk::get_building_id(dst_base.pos);

            // 攻击战力是包括所有直所有攻击目标的战力,防守战力只能限于城市区域内的战力
            int atk_power = ai::force_attack_base_troops[force.get_id()][dst_base.get_id()];
            int def_power = ai::base_around_self_troops[dst_base.get_id()] + ch::city_spec_troops(dst_base) / 2 + pk::get_troops(dst_base);

            int status = atk_power - def_power;
            string status_info = "";

            // 如果已经接近战败,则不支援.
            if (atk_power < 6000 and dst_base.get_force_id() != -1)
                return false;

            if (调试模式2.v)  pk::trace(pk::format("5对{}的据点选择.找到可用据点{},({}军))", pk::decode(pk::get_name(dst_base)), pk::decode(pk::get_name(pk::get_building(src_target))), pk::decode(pk::get_name(force))));

            bool has_siege = true;
            // 检查攻城兵器库存
            int siege_dir_id = (pk::has_tech(src_base, 技巧_木兽开发)) ? 兵器_木兽 : 兵器_冲车;
            int siege_rng_id = (pk::has_tech(src_base, 技巧_投石开发)) ? 兵器_投石 : 兵器_井阑;
            int amt_siege_dir = pk::get_weapon_amount(src_base, siege_dir_id); // 冲车系数量
            int amt_siege_rng = pk::get_weapon_amount(src_base, siege_rng_id); // 井栏系数量
            int total_siege_amount = amt_siege_rng + amt_siege_dir;
            if ((amt_siege_rng + amt_siege_dir) < 2)
                has_siege = false;
            ; // 没有攻城兵器

            bool cmd = false;

            if (调试模式2.v)  pk::trace(pk::format("6对{}的据点选择.找到可用据点{},({}军,status{}))", pk::decode(pk::get_name(dst_base)), src_target, pk::decode(pk::get_name(force)), status));

            if (status >= 10000 * 2 and ai::base_around_enemy_troops[dst_base.get_id()] > 20000 and atk_power > 20000)
            {
                status_info = "进攻优势,进入攻城阶段,兵器优先";
                int max_unit = (pk::enemies_around(src_base)) ? 1 : max_unit_combat;
                int num_atk_support_unit = count_atk_unit_type(src_base, dst_base, 部队类型_战斗, /*siege_weapon*/ true);
                bool siege = (pk::enemies_around(src_base) or num_atk_support_unit > max_unit_siege) ? false : true;
                cmd = (push_attack_order(dst_base, src_base, 部队类型_战斗, /*siege_weapon*/ (has_siege ? siege : false), /*max_unit*/ pk::min((has_siege ? total_siege_amount : 5), max_unit)) or cmd); // 攻城部队
            }
            else if (ch::is_gate(dst_base.get_id()) and status >= 0)
            {
                status_info = "对关隘进攻,兵器优先";
                int max_unit = (pk::enemies_around(src_base)) ? 1 : max_unit_combat;
                int num_atk_support_unit = count_atk_unit_type(src_base, dst_base, 部队类型_战斗, /*siege_weapon*/ true);
                bool siege = (pk::enemies_around(src_base) or num_atk_support_unit > max_unit_siege) ? false : true;
                cmd = (push_attack_order(dst_base, src_base, 部队类型_战斗, /*siege_weapon*/ (has_siege ? siege : false), /*max_unit*/ pk::min((has_siege ? total_siege_amount : 5), max_unit)) or cmd); // 攻城部队
            }
            else if (status >= -1 * 10000)
            {
                status_info = "攻守平衡";
                int max_unit = (pk::enemies_around(src_base)) ? 1 : max_unit_combat;
                int num_atk_support_unit = count_atk_unit_type(src_base, dst_base, 部队类型_战斗, /*siege_weapon*/ true);
                bool siege = (pk::enemies_around(src_base) or num_atk_support_unit > max_unit_siege) ? false : true;
                cmd = (push_attack_order(dst_base, src_base, 部队类型_战斗, /*siege_weapon*/ false, /*max_unit*/ max_unit) or cmd); // 战斗部队
            }
            else if (status < -2 * 10000 and status > -5 * 10000)
            {
                status_info = "进攻处于劣势";
                int max_unit = (pk::enemies_around(src_base)) ? 1 : max_unit_combat;
                cmd = (push_attack_order(dst_base, src_base, 部队类型_战斗, /*siege_weapon*/ false, /*max_unit*/ max_unit) or cmd); // 战斗部队
            }

            else if (status < -5 * 10000 and atk_power < 10000)
            {
                status_info = "攻势即将瓦解,无法支援";
                cmd = true;
            }

            if (调试模式.v)
            {
                pk::force @def_force = pk::get_force(dst_base.get_force_id());
                pk::force @atk_force = force;
                string dst_name = pk::decode(pk::get_name(dst_base));
                string src_name = pk::decode(pk::get_name(src_base));
                string def_force_name;
                string atk_force_name;
                if (def_force !is null)
                {
                    def_force_name = pk::decode(pk::get_name(pk::get_person(def_force.kunshu)));
                    atk_force_name = pk::decode(pk::get_name(pk::get_person(atk_force.kunshu)));
                }

                if (cmd)
                    pk::trace(pk::format("进攻支援:{}军从{}出征→{}军{},目前{}", atk_force_name, src_name, def_force_name, dst_name, status_info));
            }
            return true;
        }

        int max_unit_combat = pk::max(1, pk::min(12, 据点进攻支援_战斗部队数));
        int max_unit_siege = pk::max(1, pk::min(5, 据点进攻支援_攻城部队数));

        //---------------------------------------------------------------------------------------
        bool push_attack_order(pk::building @dst_base, pk::building @src_base, int attack_type, bool siege_weapon = false, int max_unit = 1)
        {
            // 进攻出发据点
            int src_id = src_base.get_id();
            int dst_id = dst_base.get_id();

            // 出击命令条件
            int unit_count = 0;
            int push_count = 0; // push次数检查变量
            int 已出征兵力 = ai::force_attack_base_troops[force_t.get_id()][dst_base.get_id()];
            int 据点范围己方兵力 = ai::base_around_self_troops[dst_base.get_id()];
            int 玩家修正 = (dst_base.is_player() ? 200000 : 0);
            if (pk::get_scenario().difficulty == 难易度_初级) 玩家修正 = 0;
            if (pk::get_scenario().difficulty == 难易度_上级) 玩家修正 = 5 * 10000;
            if (pk::get_scenario().difficulty == 难易度_超级) 玩家修正 = 10 * 10000;
            int 最大兵力 = 10 * 10000 + 据点范围己方兵力 * 2 + pk::get_troops(dst_base) + ch::city_spec_troops(dst_base) + 玩家修正;
            if (dst_base.get_id() >= 城市_末) 最大兵力 /= 2;
            if (dst_base.get_force_id() == -1) pk::min(最大兵力, 30000);

            if (调试模式2.v)  pk::trace(pk::format("7对{}的进攻,从{}出发,unit_count{},  max_unit{}, push_count{},已出征兵力{}))", pk::decode(pk::get_name(dst_base)), pk::decode(pk::get_name(src_base)), unit_count, max_unit, push_count, 已出征兵力));

            // 在出发据点上循环执行出击命令
            //最大兵力不超过野战部队+据点兵+封地兵+10万

            siege_count = 0;
            unit_count = 0;
            while (unit_count < max_unit and push_count < max_unit and 已出征兵力 < 最大兵力)
            {
                push_count += 1;
                if (attack_type == 部队类型_战斗 and !siege_weapon)
                {
                    if (调试模式2.v)  pk::trace(pk::format("8对{}的进攻,从{}出发))", pk::decode(pk::get_name(dst_base)), pk::decode(pk::get_name(src_base))));
                    int unit_id = push_battle_unit(src_base, dst_base, true, 0 /*type 0为进攻,1为防御*/);
                    if (unit_id != -1)
                    {
                        unit_count += 1; // 战斗部队计数
                        if (is_siege_weapon(pk::get_unit(unit_id).weapon))
                            siege_count += 1; // 战斗部队计数
                        if (!list_attack_base.contains(src_base))
                            list_attack_base.add(src_base);
                    }
                }
                else if (attack_type == 部队类型_战斗 and siege_weapon)
                {
                    int unit_id = push_siege_unit(src_base, dst_base, true);
                    if (unit_id != -1)
                    {
                        unit_count += 1; // 战斗部队计数
                        if (is_siege_weapon(pk::get_unit(unit_id).weapon))
                            siege_count += 1; // 战斗部队计数
                        if (!list_attack_base.contains(src_base))
                            list_attack_base.add(src_base);
                    }
                }
            }

            if (unit_count > 0)
                return true;

            return false;
        }

        //******************************************正在向目标敌方据点行进的部队数量 ***************************************************************
        int count_atk_unit_type(pk::building @src_base, pk::building @dst_base, int check_type, bool siege_weapon = false)
        {
            int count = 0;
            if (!pk::is_alive(src_base) or !pk::is_alive(dst_base))
                return -1;
            int src_id = src_base.get_id();
            int dst_id = dst_base.get_id();
            if (src_id == dst_id)
                return -1;

            pk::force @force = pk::get_force(src_base.get_force_id());
            pk::array<pk::unit @> arr_unit = pk::list_to_array(pk::get_unit_list(force));
            for (int i = 0; i < int(arr_unit.length); i++)
            {
                pk::unit @unit = arr_unit[i];
                int service_id = pk::get_service(unit);

                bool is_valid_type = false;
                if (check_type == 部队类型_战斗)
                {
                    if (siege_weapon and is_siege_weapon(pk::get_ground_weapon_id(unit)))
                        is_valid_type = (unit.type == check_type);
                    else if (!siege_weapon and !is_siege_weapon(pk::get_ground_weapon_id(unit)))
                        is_valid_type = (unit.type == check_type);
                }

                if (is_valid_type and service_id == src_id and unit.target_type == 部队任务对象_据点)
                {
                    pk::building @building_t = pk::get_building(unit.target);
                    if (pk::is_alive(building_t) and building_t.get_id() == dst_id and pk::is_enemy(unit, building_t))
                        count++;
                }
            }
            return count;
        }

        //******************************************* 获取距离友方据点  ****************************************************************
        pk::building @dst_t;
        int find_near_self_base(pk::building @dst, pk::force @force, int type)
        {
            int best_src = -1;
            int best_distance = 1;
            int dst_id = dst.get_id();
            @dst_t = @dst;
            pk::list<pk::building @> src_list;
            if (dst_id >= 据点_末 or dst_id == -1)
                return -1;

            // 搜索友方据点
            for (int i = 0; i < 据点_末; i++)
            {
                pk::building @src = pk::get_building(i);
                int src_id = src.get_id();

                if (dst_id == src_id)
                    continue;

                if (pk::is_player_controlled(src))
                    continue;

                if (src.is_player() and type == 0)
                    continue;


                int ref_troops = ai::retained_troops[src.get_id()];

                //防御状态的时候,应出尽出,但是进攻的时候要尽量一次性出兵,避免葫芦娃救爷爷

                if (type == 0)ref_troops += ((i < 据点_末) ? 15000 : 10000);
                if (type == 1)ref_troops /= 2;
                int count_enemy = 0;
                for (int p = 0; p < 6; p++)
                {
                    int neighbor = pk::get_neighbor_area_building(i, p);
                    pk::building @neighbor_choice = pk::get_building(neighbor);
                    if (neighbor_choice.get_force_id() != src.get_force_id())  count_enemy++;
                }
                if (count_enemy == 1 and pk::get_building_distance(i, dst_id) == 1)
                    ref_troops /= 2;

                if (pk::get_food(src) < ref_troops * 2)
                    continue;



                if (调试模式4.v)
                    pk::trace(pk::format("1对{}进行支援.选中{},留存兵力{},类型{}", pk::decode(pk::get_name(dst)), pk::decode(pk::get_name(src)), ref_troops, type));


                if (!ch::is_valid_routepath(i, dst.get_id(), pk::get_building(i).get_force_id()))
                    continue;


                if (调试模式4.v)
                    pk::trace(pk::format("1.2对{}进行支援.选中{},留存兵力{},类型{}", pk::decode(pk::get_name(dst)), pk::decode(pk::get_name(src)), ref_troops, type));


                //只要路通,10以内都可以去,城市距离为1也可以
                if (unit_distance[i][dst_id] >= 10 and pk::get_city_distance(pk::get_city_id(src.pos), pk::get_city_id(dst.pos)) > 1)
                    continue; // 真实距离太远

                if (调试模式4.v)
                    pk::trace(pk::format("1.3对{}进行支援.选中{},留存兵力{},类型{}", pk::decode(pk::get_name(dst)), pk::decode(pk::get_name(src)), ref_troops, type));


                if (src.energy < 100)
                    continue;

                if (调试模式4.v)
                    pk::trace(pk::format("2对{}进行支援.选中{},被攻击的兵力{},类型{}", pk::decode(pk::get_name(dst)), pk::decode(pk::get_name(src)), ai::base_attacked_troops[i], type));

                if (ai::base_attacked_troops[i] > 10000)
                    continue; // 被攻击的据点例外


                if (调试模式4.v)
                    pk::trace(pk::format("3对{}进行支援.选中{},被攻击的兵力{},类型{}", pk::decode(pk::get_name(dst)), pk::decode(pk::get_name(src)), ai::base_attacked_troops[i], type));

                if (!pk::is_enemy(src, dst) and dst.get_force_id() > -1 and type == 0)
                    continue; // 进攻的时候,只看敌对据点,非敌对的据点排除 //空据点也可以考虑


                if (调试模式4.v)
                    pk::trace(pk::format("4对{}进行支援.选中{},留存兵力{},类型{}", pk::decode(pk::get_name(dst)), pk::decode(pk::get_name(src)), ref_troops, type));

                if (src.get_force_id() != force.get_id() and type == 0)
                    continue; // 进攻的时候,支援势力要是主体势力才行


                if (调试模式4.v)
                    pk::trace(pk::format("5对{}进行支援.选中{},留存兵力{},类型{}", pk::decode(pk::get_name(dst)), pk::decode(pk::get_name(src)), ref_troops, type));

                if (pk::is_enemy(src, dst) and type == 1)
                    continue; // 防御的时候,只看己方据点,敌对的据点排除


                if (调试模式4.v)
                    pk::trace(pk::format("6对{}进行支援.选中{},留存兵力{},类型{}", pk::decode(pk::get_name(dst)), pk::decode(pk::get_name(src)), ref_troops, type));

                if (ai::base_in_range_enemy_troops[i] > 0)
                    continue; // 自身战斗状态排除


                if (调试模式4.v)
                    pk::trace(pk::format("7对{}进行支援.选中{},留存兵力{},类型{}", pk::decode(pk::get_name(dst)), pk::decode(pk::get_name(src)), ref_troops, type));

                auto person_list = pk::get_idle_person_list(src);
                if (person_list.count == 0)
                    continue; // 武将不足


                if (调试模式4.v)
                    pk::trace(pk::format("8对{}进行支援.选中{},留存兵力{},现有兵力{}", pk::decode(pk::get_name(dst)), pk::decode(pk::get_name(src)), ref_troops, int(pk::get_troops(src))));

                if (int(pk::get_troops(src)) - ref_troops < 0)
                    continue; // 兵力不足

                if (调试模式2.v)
                    pk::trace(pk::format("9对{}进行支援.选中{},留存兵力{},类型{}", pk::decode(pk::get_name(dst)), pk::decode(pk::get_name(src)), ref_troops, type));

                int src_troops = pk::get_troops(src);
                int src_food = pk::get_food(src);

                int person_count = pk::get_person_list(src, pk::mibun_flags(身份_君主, 身份_都督, 身份_太守, 身份_一般)).count;
                int idle_p_count = pk::get_idle_person_list(src).count;

                int weapon_amount = 0;

                for (int j = 兵器_枪; j <= 兵器_战马; j++) // 统计枪、弓箭等兵器数量
                {
                    weapon_amount += pk::get_weapon_amount(src, j);
                }

                // 符合派兵条件（拥有武将、出兵数量符合要求、拥有足够的兵器、食物）
                if (idle_p_count > 0 and weapon_amount >= ref_troops and src_food >= int(1.0f * ref_troops))
                {
                    src_list.add(src); // 可派兵的据点列表
                    if (type == 1 and 调试模式2.v)
                        pk::trace(pk::format("10对{}进行支援.加入列表{}", pk::decode(pk::get_name(dst)), pk::decode(pk::get_name(src))));
                }
            }

            // 多因子排序
            if (src_list.count == 0)
                return -1;
            else
            {
                src_list.sort(function(a, b) {
                    // int final_a = ai::base_atk_power[a.get_id()];
                    // int final_b = ai::base_atk_power[b.get_id()];
                    //由于ai指令不会中途刷新,因此要切换为实际兵力.
                    int final_a = pk::get_troops(a);
                    int final_b = pk::get_troops(b);

                    return final_a > final_b;
                });

                return src_list[0].get_id();
            }
        }
        //*******************************************  野战部队出征 ****************************************************************
        int push_battle_unit(pk::building @src_base, pk::building @dst_base, bool do_cmd = true, int type = 0)
        {

            if (调试模式2.v)  pk::trace(pk::format("11对{}的进攻,从{}出发))", pk::decode(pk::get_name(dst_base)), pk::decode(pk::get_name(src_base))));

            if (!pk::is_alive(src_base) or !pk::is_alive(dst_base) or pk::is_player_controlled(src_base))
                return -1;

            // 根据敌方兵力数,计算留存量,可用兵力小于留存量则不支援.
            int ref_troops = ai::retained_troops[src_base.get_id()];

            //防御的时候应该更积极的支援
            if (type == 1)ref_troops /= 2;

           /// 和玩家相邻不止一个,而且进攻的不为玩家据点,则非常保守
            if (ch::get_neighbor_player_base(src_base) >= 1 and !dst_base.is_player())
                ref_troops += ch::get_neighbor_player_base(src_base) * 10000 + 10000;

            if (调试模式2.v)
                pk::trace(pk::format("12对{}的进攻,从{}出发,留存{},现有{}))", pk::decode(pk::get_name(dst_base)), pk::decode(pk::get_name(src_base)), ref_troops, pk::get_troops(src_base)));

            if (int(pk::get_troops(src_base)) < ref_troops)
                return -1; // 兵力不足

            auto person_list = pk::get_idle_person_list(src_base);
            if (person_list.count == 0)
                return -1; // 武将不足

            if (调试模式2.v)  pk::trace(pk::format("13对{}的进攻,从{}出发,留存{},现有{}))", pk::decode(pk::get_name(dst_base)), pk::decode(pk::get_name(src_base)), ref_troops, pk::get_troops(src_base)));

            //********************  武将能力打分  **********************
            person_list.sort(function(a, b) {
                int a_score = a.stat[武将能力_武力] * UNIT_ATTR::攻武占比 + a.stat[武将能力_统率] * UNIT_ATTR::攻统占比 * 2 + a.stat[武将能力_智力] * UNIT_ATTR::防智占比;
                int b_score = b.stat[武将能力_武力] * UNIT_ATTR::攻武占比 + b.stat[武将能力_统率] * UNIT_ATTR::攻统占比 * 2 + b.stat[武将能力_智力] * UNIT_ATTR::防智占比;
                // 考虑武将能力
                return (a_score > b_score);
            });

            int person_id = -1;

            for (int i = 0; i < person_list.count; i++)
            {
                if (person_list[i].stat[武将能力_统率] + person_list[i].stat[武将能力_武力] / 2 + person_list[i].stat[武将能力_智力] / 2 < 80)
                    continue;

                person_id = person_list[i].get_id();
                if (person_id >= 0) break;
            }

            if (person_id == -1) return -1;
            pk::person @leader = pk::get_person(person_id);

            if (调试模式2.v)  pk::trace(pk::format("14对{}的进攻,从{}出发,留存{},现有{}))", pk::decode(pk::get_name(dst_base)), pk::decode(pk::get_name(src_base)), ref_troops, pk::get_troops(src_base)));

            // 计算出发部队兵力：超过基准兵力，确认指挥能力
            int reinforce_troops = pk::min(20000, pk::get_command(leader), pk::max(1, pk::get_troops(src_base) - ref_troops));

            // 选择最佳的武器
            int ground_weapon_id = 兵器_剑;
            int ground_weapon_score = 0;
            int water_weapon_id = 兵器_走舸;
            int unit_troops = reinforce_troops;

            //*******************  陆地兵器  ******************
            // 选择陆上武器
            ground_weapon_id = get_ground_weapon(src_base, leader, dst_base, type).first;
            ground_weapon_score = get_ground_weapon(src_base, leader, dst_base, type).second;

            //pk::trace(pk::decode(pk::get_name(leader)) + get_weapon_name(ground_weapon_id) + "ground_weapon_id" + ground_weapon_id + "ground_weapon_score:" + ground_weapon_score + ",unit_troops :" + unit_troops);

            if (ground_weapon_score == 0 or ground_weapon_id == 0)
                return -1; // 兵器不足

            if (调试模式2.v)  pk::trace(pk::format("15对{}的进攻,从{}出发,留存{},现有{}))", pk::decode(pk::get_name(dst_base)), pk::decode(pk::get_name(src_base)), ref_troops, pk::get_troops(src_base)));

            if (ground_weapon_id <= 兵器_战马)
            {
                unit_troops = pk::min(unit_troops, pk::get_weapon_amount(src_base, ground_weapon_id));
                if (unit_troops < 5000) return -1;
            }

            if (调试模式2.v)  pk::trace(pk::format("16对{}的进攻,从{}出发,留存{},现有{}))", pk::decode(pk::get_name(dst_base)), pk::decode(pk::get_name(src_base)), ref_troops, pk::get_troops(src_base)));

            //********************  水上兵器  ***********************
            // 选择水上武器
            if (building_sea_enemy_count(src_base) > 0 and building_sea_enemy_count(dst_base) > 0)
            {
                if (leader.tekisei[兵种_水军] == 适性_C)
                    water_weapon_id = 兵器_走舸;
                else
                {
                    if (pk::get_weapon_amount(src_base, 兵器_楼船) > 0)
                        water_weapon_id = 兵器_楼船;
                    else if (pk::get_weapon_amount(src_base, 兵器_斗舰) > 0)
                        water_weapon_id = 兵器_斗舰;
                    else
                        water_weapon_id = 兵器_走舸;
                }
            }
            else
                water_weapon_id = 兵器_走舸;

         //**********************  新粮草计算  **********************
         // 使用新的unit_distance计算部队消耗
         // 最终带粮基准值为路上*2+12回合战斗
            int base_weight = unit_distance[src_base.get_id()][dst_base.get_id()];

            if (pk::get_food(src_base) > pk::get_troops(src_base) * 5 and pk::get_food(src_base) > 120000)
                base_weight += 1;

            float rate = (base_weight * 2 + 12);
            // if ((ground_weapon_id > 兵器_战马 and ground_weapon_id < 兵器_走舸) or ground_weapon_id == 兵器_戟) // 跑得慢的多加一些
            //     rate *= 1.25f;

            rate = pk::min(rate, 35.0); // 无论如何都不会超过350天,防止带的太多影响城市粮草
            int unit_food = int(unit_troops * rate / 10);

            if (调试模式2.v)  pk::trace(pk::format("17对{}的进攻,从{}出发,带粮{},城市现有粮{},城市剩余兵{}))", pk::decode(pk::get_name(dst_base)), pk::decode(pk::get_name(src_base)), unit_food, pk::get_food(src_base), pk::get_troops(src_base) - unit_troops));

            if (int(pk::get_food(src_base) - int(unit_food)) < int(pk::get_troops(src_base)))
            {
                int 最大可带粮 = pk::max(0, int(pk::get_food(src_base)) - int(pk::get_troops(src_base) * 0.5));
                int 最大兵力 = 最大可带粮 / 2;
                unit_troops = pk::min(最大兵力, unit_troops);
                if (unit_troops < 5000) return -1;
            }

            if (int(pk::get_troops(src_base)) - unit_troops < 5000)
                return -1;

            if (unit_troops < 5000)
                return -1;

            if (调试模式2.v)  pk::trace(pk::format("18对{}的进攻,从{}出发,留存{},现有{}))", pk::decode(pk::get_name(dst_base)), pk::decode(pk::get_name(src_base)), ref_troops, pk::get_troops(src_base)));

            //*************************** 野战部队出征指令  ********************
            if (do_cmd)
            {
                // 出征命令信息生成
                pk::com_march_cmd_info cmd;
                @cmd.base = @src_base;
                cmd.type = 部队类型_战斗;
                cmd.member[0] = leader.get_id();
                cmd.gold = (pk::get_gold(src_base) >= 1000) ? int(pk::min(1000.f, pk::get_gold(src_base) * 0.1f)) : 0;
                cmd.troops = pk::max(1, unit_troops);
                cmd.weapon_id[0] = ground_weapon_id;
                cmd.weapon_id[1] = water_weapon_id;
                cmd.weapon_amount[0] = (is_siege_weapon(ground_weapon_id)) ? 1 : pk::max(1, unit_troops);
                cmd.weapon_amount[1] = (water_weapon_id == 兵器_走舸) ? 0 : 1;
                cmd.food = pk::min(50000, unit_food);


                cmd.order = (pk::is_enemy(src_base, dst_base) ? 部队任务_征服 : 部队任务_移动);

                if (dst_base.get_force_id() == -1) cmd.order = 部队任务_攻击;

                cmd.target_pos = dst_base.get_pos(); // 目标是战斗中的据点

                //ai出征优化::main.march_modify(cmd,1/*0防御，1攻击，2建设，3运输*/);//实际上前方只用给出大概的主将和目标就行了，剩下的全部可以走优化

                leader.action_done = true;
                int unit_id = pk::command(cmd);

                pk::unit @unit_cmd = pk::get_unit(unit_id);
                if (pk::is_alive(unit_cmd))
                {
                    unit_cmd.action_done = true;
                    if (type == 0) ai::force_attack_base_troops[force_t.get_id()][dst_base.get_id()] += unit_cmd.troops;

                    if (调试模式.v)
                    {
                        string src_name = pk::decode(pk::get_name(src_base));
                        string dst_name = pk::decode(pk::get_name(dst_base));
                        string unit_name = pk::decode(pk::get_name(leader));
                        string order_str = get_order_info(unit_cmd.order);
                        string cmd_info;


                        if (pk::is_enemy(src_base, dst_base))
                            cmd_info = "进攻支援";
                        else if (ch::is_gate(dst_base.get_id()))
                        {
                            if (src_base.get_force_id() == dst_base.get_force_id())
                                cmd_info = "防御支援-关隘支援-弩兵优先";
                            else
                                cmd_info = "同盟支援-关隘支援-弩兵优先";
                        }
                        else
                        {
                            if (src_base.get_force_id() == dst_base.get_force_id())
                                cmd_info = "防御支援";
                            else
                                cmd_info = "同盟支援";
                        }
                        if (dst_base.get_force_id() == -1)  cmd_info = "空城攻击";
                        pk::trace(pk::format("{}: {}队从 {}出征:→ {}", cmd_info, unit_name, src_name, dst_name));

                    }
                    return unit_id;
                }
            }

            return -1;
        }

        //******************************************* 武器选择函数   ****************************************************************
        pk::int_int get_ground_weapon(pk::building @base, pk::person @leader, pk::building @dst_base, int type)
        {
            array<int> heishu_score(兵器_末, 0);    // 适性评分，是否可以参考副将补全
            array<bool> can_march(兵器_末, false);  // 是否有足够兵器可出征
            array<int> tech_score(兵器_末, 0);      // 已研究科技评分
            array<int> ling_score(兵器_末, 0);      // 根据态势调整
            array<int> skill_score(兵器_末, 0); // 总特技评分
            array<int> all_score(兵器_末, 0);       // 兵器和适性的总评分

            int siege_max = 1;
            siege_max += pk::max((int(pk::get_troops(base) / 5000) + unit_count) / 5 - 1, 0);   //模拟预估计算总部队数
            siege_max = pk::min(siege_max, 2);



            if (type == 1) //防守策略
            {
                if (ch::is_gate(dst_base.get_id())) //对关隘进行防守
                {
                    ling_score[兵器_弩] += 3;
                    ling_score[兵器_战马] -= 3;
                }
                else
                    ling_score[兵器_战马] += 3;    //对己方据点防守支援的时候,由于不涉及攻城战,且需要时效性,因此骑兵优先
            }

            if (type == 0) //进攻策略
            {
                if (ch::is_gate(dst_base.get_id())) //对关隘进行攻城支援
                    ling_score[兵器_战马] -= 3;
            }

            pk::force @force0 = pk::get_force(leader.get_force_id());
            for (int i = 0; i < 兵器_走舸; i++)
            {
                if (leader.tekisei[pk::equipment_id_to_heishu(i)] < 适性_B)
                    can_march[i] = false;

                else if ((i == 兵器_冲车 or i == 兵器_木兽) and type == 1)// 冲车木兽不在防御时出动
                    can_march[i] = false;

                else if ((i == 兵器_冲车 or i == 兵器_木兽 or i == 兵器_井阑 or i == 兵器_投石) and leader.tekisei[pk::equipment_id_to_heishu(i)] < 适性_A)//野战部队除非有S兵器,否则不出兵器
                    can_march[i] = false;


                else if (ch::check_weapon_able(base, i))
                    can_march[i] = true;

                if ((i == 兵器_冲车 or i == 兵器_木兽 or i == 兵器_井阑 or i == 兵器_投石) and siege_count >= siege_max)//野战部队除非有S兵器,否则不出兵器
                    can_march[i] = false;



                if (can_march[i])
                {
                    if (i > 兵器_战马 and type == 0)  ling_score[i] -= 1; //进攻支援的时候,由于这是野战计算,因此还是要降低兵器权重.
                    if (i > 兵器_战马 and type == 1)  ling_score[i] -= 3; //防御支援的时候,井阑移动速度过慢,很不适合作为防御支援,除非不得已或者只适合井阑.

                    if (i == 兵器_剑)  heishu_score[i] = 0;
                    else heishu_score[i] = leader.tekisei[pk::equipment_id_to_heishu(i)];
                    tech_score[i] = ch::get_tech_score(force0, i);

                    int skill_id = leader.skill;
                    if (skill_id < 211 and skill_id >-1)
                    {
                    //pk::trace(pk::decode(pk::get_name(leader)) + get_weapon_name(i) + "i:" +i + "skill_id :" +skill_id );
                        skill_score[i] = ai出征优化::skill_score[skill_id][i];
                    }
                    all_score[i] = heishu_score[i] * 3 + tech_score[i] + skill_score[i] + ling_score[i];

                    //pk::trace(pk::decode(pk::get_name(leader)) + get_weapon_name(i) + "科技分:" + tech_score[i] + "特技分:" + skill_score[i] + ",适性分:" + heishu_score[i] * 3 + ",态势分:" + ling_score[i] + ",总分:" + all_score[i]);

                }


            }

            return pk::int_int(get_arr_max(all_score));
        }

        pk::int_int get_arr_max(array<int> score)
        {
            int best_score = 0;
            int id = 0;
            for (int i = 0; i < int(score.length); i++)
            {
                if (score[i] > best_score)
                {
                    best_score = score[i];
                    id = i;
                }
            }

            return pk::int_int(id, best_score);
        }

        //***************************  攻城部队出征处理  ********************
        int push_siege_unit(pk::building @src_base, pk::building @dst_base, bool do_cmd = true)
        {
            if (调试模式2.v)  pk::trace(pk::format("13,攻城车对{}的进攻,从{}出发))", pk::decode(pk::get_name(dst_base)), pk::decode(pk::get_name(src_base))));

            if (!pk::is_alive(src_base) or pk::is_player_controlled(src_base))
                return -1;

            // 根据敌方兵力数,计算留存量,可用兵力小于留存量则不支援.
            int ref_troops = ai::retained_troops[src_base.get_id()];

            /// 和玩家相邻不止一个,而且进攻的不为玩家据点,则非常保守
            if (ch::get_neighbor_player_base(src_base) >= 1 and !dst_base.is_player())
                ref_troops += ch::get_neighbor_player_base(src_base) * 10000 + 10000;

            if (int(pk::get_troops(src_base)) < ref_troops)
                return -1; // 兵力不足

            int person_count = pk::get_person_list(src_base, pk::mibun_flags(身份_君主, 身份_都督, 身份_太守, 身份_一般)).count;
            if (person_count <= 3)
                return -1; // 武将不足

            auto person_list = pk::get_idle_person_list(src_base);
            if (person_list.count == 0)
                return -1; // 武将不足

            if (调试模式2.v)  pk::trace(pk::format("14,攻城车对{}的进攻,从{}出发))", pk::decode(pk::get_name(dst_base)), pk::decode(pk::get_name(src_base))));

            // 检查攻城兵器库存
            int siege_dir_id = (pk::has_tech(src_base, 技巧_木兽开发)) ? 兵器_木兽 : 兵器_冲车;
            int siege_rng_id = (pk::has_tech(src_base, 技巧_投石开发)) ? 兵器_投石 : 兵器_井阑;
            int amt_siege_dir = pk::get_weapon_amount(src_base, siege_dir_id); // 直接攻城兵器数量
            int amt_siege_rng = pk::get_weapon_amount(src_base, siege_rng_id); // 间接攻城兵器数量
            if ((amt_siege_rng + amt_siege_dir) == 0)
                return -1; // 没有攻城兵器

            if (调试模式2.v)  pk::trace(pk::format("15,攻城车对{}的进攻,从{}出发))", pk::decode(pk::get_name(dst_base)), pk::decode(pk::get_name(src_base))));

            // 根据攻城特技、统率力与武力的高低排序，优先选择攻城特技，其次是体力恢复特技，最后根据兵种适性和武将能力排序
            person_list.sort(function(a, b) {
                // 优先选择攻城特技
                bool a_skill = (pk::has_skill(a, 特技_工神) or pk::has_skill(a, 特技_攻城) or pk::has_skill(a, 特技_射程));
                bool b_skill = (pk::has_skill(b, 特技_工神) or pk::has_skill(b, 特技_攻城) or pk::has_skill(b, 特技_射程));
                if (a_skill and !b_skill)
                    return true;
                if (!a_skill and b_skill)
                    return false;
                // 其次选择体力恢复特技
                bool a_energy = (pk::has_skill(a, 特技_奏乐) or pk::has_skill(a, 特技_诗想) or pk::has_skill(a, 特技_怒发));
                bool b_energy = (pk::has_skill(b, 特技_奏乐) or pk::has_skill(b, 特技_诗想) or pk::has_skill(b, 特技_怒发));
                if (a_energy and !b_energy)
                    return true;
                if (!a_energy and b_energy)
                    return false;
                // 再根据兵种适性排序
                if (a.tekisei[兵种_兵器] != b.tekisei[兵种_兵器])
                    return (a.tekisei[兵种_兵器] > b.tekisei[兵种_兵器]);
                // 最后根据武将能力排序
                return (a.stat[武将能力_武力] + a.stat[武将能力_统率]) > (b.stat[武将能力_武力] + b.stat[武将能力_统率]);
            });

            int person_id = -1;
            for (int i = 0; i < person_list.count; i++)
            {
                if (person_list[i].stat[武将能力_统率] + person_list[i].stat[武将能力_武力] / 2 + person_list[i].stat[武将能力_智力] / 2 < 80)
                    continue;

                if (person_list[i].tekisei[兵种_兵器] <= 适性_B)  //适性不足
                    continue;

                person_id = person_list[i].get_id();
                if (person_id > 0) break;
            }
            if (person_id == -1) return -1;
            pk::person @leader = pk::get_person(person_id);

            if (调试模式2.v)  pk::trace(pk::format("16,攻城车对{}的进攻,从{}出发))", pk::decode(pk::get_name(dst_base)), pk::decode(pk::get_name(src_base))));


            // 计算部队兵力：超出基准兵力，检查指挥兵力
            int reinforce_troops = pk::min(50000, pk::get_command(leader), pk::max(1, pk::get_troops(src_base) - ref_troops));

            // 选择最佳武器
            int ground_weapon_id = 兵器_剑;
            int water_weapon_id = 兵器_走舸;

            int water_weapon = 兵器_楼船;
            if (pk::has_tech(src_base, 技巧_开发投石))
                water_weapon = 兵器_斗舰;

               //必须经过水域的时候,有船就用船.不管是谁
            if (must_water_count[src_base.get_id()][dst_base.get_id()] >= 2)
            {
                if (pk::get_weapon_amount(src_base, water_weapon) > 0)
                    water_weapon_id = water_weapon;
            }

            else if (option_water_count[src_base.get_id()][dst_base.get_id()] >= 2)
            {
                //充足的时候随便用
                if (pk::get_weapon_amount(src_base, water_weapon) >= 8)
                    water_weapon_id = water_weapon;
                                //充足的时候随便用
                else
                {
                    if (leader.tekisei[兵种_水军] == 适性_C)
                        water_weapon_id = 兵器_走舸;
                    else if (pk::get_weapon_amount(src_base, water_weapon) > 0)
                    {
                        water_weapon_id = water_weapon;
                    }

                }

            }

            int unit_troops = reinforce_troops;

            // 从间接攻城兵器开始优先选择(特技为间接，攻城特技为直接兵器优先安排)
            if (amt_siege_rng > 0 and pk::has_skill(leader, 特技_射程))
                ground_weapon_id = siege_rng_id;
            else if (amt_siege_dir > 0 and pk::has_skill(leader, 特技_攻城))
                ground_weapon_id = siege_dir_id;
            else if (amt_siege_rng > 0)
                ground_weapon_id = siege_rng_id;
            else if (amt_siege_dir > 0)
                ground_weapon_id = siege_dir_id;

         //**********************  新粮草计算  **********************
         // 使用新的unit_distance计算部队消耗
         // 最终带粮基准值为路上*2+12回合战斗
            int base_weight = unit_distance[src_base.get_id()][dst_base.get_id()];

            if (pk::get_food(src_base) > pk::get_troops(src_base) * 5 and pk::get_food(src_base) > 120000)
                base_weight += 1;

            float rate = (base_weight * 2 + 12);
            // if ((ground_weapon_id > 兵器_战马 and ground_weapon_id < 兵器_走舸) or ground_weapon_id == 兵器_戟) // 跑得慢的多加一些
            //     rate *= 1.25f;

            rate = pk::min(rate, 35.0); // 无论如何都不会超过350天,防止带的太多影响城市粮草
            int unit_food = int(unit_troops * rate / 10);

            if (int(pk::get_food(src_base) - int(unit_food)) < int(pk::get_troops(src_base)))
            {
                int 最大可带粮 = pk::max(0, int(pk::get_food(src_base)) - int(pk::get_troops(src_base) * 0.5));
                int 最大兵力 = 最大可带粮 / 2;
                unit_troops = pk::min(最大兵力, unit_troops);
                if (unit_troops < 5000) return -1;
            }

            if (int(pk::get_troops(src_base)) - unit_troops < 5000)
                return -1;

            if (unit_troops < 5000)
                return -1;

            if (调试模式2.v)  pk::trace(pk::format("17,攻城车对{}的进攻,从{}出发))", pk::decode(pk::get_name(dst_base)), pk::decode(pk::get_name(src_base))));

            // 出征命令
            if (do_cmd)
            {
                // 生成出征命令信息，创建出征命令信息。
                pk::com_deploy_cmd_info cmd;
                @cmd.base = @src_base;
                cmd.type = 部队类型_战斗;
                cmd.member[0] = leader.get_id();
                cmd.gold = 0; // 攻城器械部队无法建造，因此不携带金币
                cmd.troops = pk::max(1, unit_troops);
                cmd.weapon_id[0] = ground_weapon_id;
                cmd.weapon_id[1] = water_weapon_id;
                cmd.weapon_amount[0] = (is_siege_weapon(ground_weapon_id)) ? 1 : pk::max(1, unit_troops);
                cmd.weapon_amount[1] = (water_weapon_id == 兵器_走舸) ? 0 : 1;
                cmd.food = pk::min(50000, unit_food);

                cmd.order = (src_base.get_force_id() == dst_base.get_force_id()) ? 部队任务_征服 : ((pk::is_enemy(src_base, dst_base)) ? 部队任务_征服 : 部队任务_移动); // 同势力、敌据点、盟军

                cmd.target_pos = dst_base.get_pos(); // 目标是正在战斗的据点

                // 出征。
                int unit_id = pk::command(cmd);
                leader.action_done = true;
                pk::unit @unit_cmd = pk::get_unit(unit_id);
                if (pk::is_alive(unit_cmd))
                {
                    unit_cmd.action_done = true;
                    ai::force_attack_base_troops[force_t.get_id()][dst_base.get_id()] += unit_cmd.troops;


                    if (调试模式.v)
                    {
                        string src_name = pk::decode(pk::get_name(src_base));
                        string dst_name = pk::decode(pk::get_name(dst_base));
                        string unit_name = pk::decode(pk::get_name(leader));
                        string order_str = get_order_info(unit_cmd.order);
                        string cmd_info = (pk::is_enemy(src_base, dst_base)) ? "进攻支援" : "防御支援";
                        pk::trace(pk::format("{}: {} {}: {}→{}", cmd_info, unit_name, order_str, src_name, dst_name));
                    }
                    return unit_id;
                }
            }

            return -1;
        }

        //******************************************* 攻城工具判断   ****************************************************************
        bool is_siege_weapon(int weapon_id)
        {
            if (兵器_冲车 <= weapon_id and weapon_id <= 兵器_木兽)
                return true;
            return false;
        }

        //******************************************* 水上武器判断   ****************************************************************
        int building_sea_enemy_count(pk::building @building)
        {
            // 计算海上敌对势力
            int route_type = -1;
            int sea_enemy_count = 0;
            for (int i = 0; i < 6; i++)
            {
                int neighbor_base_id = pk::get_neighbor_area_building(building.get_id(), i);
                if (neighbor_base_id >= 0 and neighbor_base_id <= 据点_末)
                {
                    route_type = pk::get_neighbor_area_route(building.get_id(), i);

                    if (pk::is_enemy(building, pk::get_building(neighbor_base_id)) and route_type == 路径_海洋)
                        sea_enemy_count++;
                }
            }
            return sea_enemy_count;
        }

        //---------------------------------------------------------------------------------------
        string get_weapon_name(int weapon_id)
        {
            string weapon_name;
            switch (weapon_id)
            {
                case 兵器_剑:
                    weapon_name = "剑兵";
                    break;
                case 兵器_枪:
                    weapon_name = "枪兵";
                    break;
                case 兵器_戟:
                    weapon_name = "戟兵";
                    break;
                case 兵器_弩:
                    weapon_name = "弓兵";
                    break;
                case 兵器_战马:
                    weapon_name = "骑兵";
                    break;
                case 兵器_冲车:
                    weapon_name = "冲车";
                    break;
                case 兵器_井阑:
                    weapon_name = "井栏";
                    break;
                case 兵器_投石:
                    weapon_name = "投石";
                    break;
                case 兵器_木兽:
                    weapon_name = "木兽";
                    break;
                case 兵器_走舸:
                    weapon_name = "走舸";
                    break;
                case 兵器_楼船:
                    weapon_name = "楼船";
                    break;
                case 兵器_斗舰:
                    weapon_name = "斗舰";
                    break;
                default:
                    weapon_name = "??";
                    break;
            }
            return weapon_name;
        }

        string get_order_info(int order)
        {
            string name;
            switch (order)
            {
                case 0:
                    name = "部队任务_待命";
                    break;
                case 1:
                    name = "部队任务_移动";
                    break;
                case 2:
                    name = "部队任务_设置";
                    break;
                case 3:
                    name = "部队任务_征服";
                    break;
                case 4:
                    name = "部队任务_撤退";
                    break;
                case 5:
                    name = "部队任务_拦截";
                    break;
                case 6:
                    name = "部队任务_护卫";
                    break;
                case 7:
                    name = "部队任务_攻城";
                    break;
                case 8:
                    name = "部队任务_修复";
                    break;
                case 9:
                    name = "部队任务_征服";
                    break;
                case 10:
                    name = "部队任务_补给";
                    break;
                case 11:
                    name = "部队任务_歼灭";
                    break;
                case 12:
                    name = "部队任务_追随";
                    break;
                case 13:
                    name = "部队任务_末";
                    break;
                default:
                    name = "部队任务_没有";
                    break;
            }

            return name;
        }

        //---------------------------------------------------------------------------------------
    };

    Main main;
}